<template>
  <div class="main-container">
    <el-form ref="createForm" :model="dataForm" :rules="rules">
    <!-- 基本配置 -->
    <div class="data-show">
      <!-- 标题 -->
      <div class="data-actions">
        <h3>基本配置</h3>
      </div>
      <!-- 内容区 -->
      <div class="data-table">
        <!-- 通用布局行 -->
        <div class="common-row row-between">
          <!-- 配置项 - 算法名称 -->
          <div class="common-item item-5">
            <label class="condition-label">模块名称</label>
            <el-form-item class="condition-input" prop="name">
              <el-input type="text" placeholder="请输入模块名称" v-model="dataForm.name" />
            </el-form-item>
          </div>
          <!-- 配置项 - 模块选择 -->
          <div class="common-item item-5">
            <label class="condition-label">选择模块库</label>
            <!-- <el-form-item class="condition-input" prop="moduleLibId">
              <el-select v-model="dataForm.moduleLibId" clearable placeholder="请选择对应的模块">
                <el-option v-for="(item, index) in moduleLibrarys" :key="index" :label="item.name" :value="item.id" />
              </el-select>
            </el-form-item> -->
            <el-form-item class="condition-input" prop="moduleLibId">
              <el-cascader 
                clearable 
                v-model="dataForm.moduleLibSelect" 
                :options="moduleLibrarys"
                :props="{
                  value: 'id',
                  label: 'name',
                  children: 'children',
                  checkStrictly: true
                }" 
                @change="selectModuleLibs"
              />
            </el-form-item>
          </div>          
        </div>
        <!-- 通用布局行 -->
        <div class="common-row">
          <div class="common-item item-10">
            <label class="condition-label">模块描述</label>
            <el-form-item class="condition-input" prop="description">
              <el-input v-model="dataForm.description" maxlength="100" type="textarea" show-word-limit rows="4" resize="none" placeholder="请输入模块描述" />
            </el-form-item>
          </div>
        </div>
      </div>
    </div>
    <!-- 算法上传 -->
    <div class="data-show">
      <!-- 标题 -->
      <div class="data-actions">
        <h3>算法上传</h3>
      </div>
      <!-- 内容区 -->
      <div class="data-table">
        <!-- 通用布局行 -->
        <div class="common-row">
          <div class="common-item item-5">
            <label class="condition-label">选择算法平台</label>
            <el-form-item class="condition-input radio-input" prop="system">
              <el-radio v-for="(item, index) in systems" :key="index" :label="item.name" :value="item.id" v-model="dataForm.system">
                <span>{{ item.name }}</span>
              </el-radio>
            </el-form-item>
          </div>
          <div class="common-item item-5">
            <label class="condition-label">是否默认</label>
            <el-form-item class="condition-input radio-input" prop="isDefault">
              <el-radio v-for="(item, index) in defaults" :key="index" :label="item.label" :value="item.value" v-model="dataForm.isDefault">
              </el-radio>
            </el-form-item>
          </div>
        </div>
        <!-- 通用布局行 -->
        <div class="common-row row-between">
          <!-- 静态链接 -->
          <div class="common-item item-10" :style="{paddingBottom: getFileListPadding(uploadObj.linkFileId)}">
            <label class="condition-label">静态链接库上传</label>
            <el-form-item class="condition-input" prop="linkFileId">
              <el-upload
                class="upload"
                :ref="uploadObj.uploadRef('linkFileId')"
                drag
                :action="uploadObj.uploadUrl"
                multiple
                :headers="uploadObj.headers"
                :show-file-list="uploadObj.linkFileId.showFileList"
                :before-upload="uploadObj.beforeUpload('linkFileId')"
                :on-success="uploadObj.onSuccess('linkFileId', dataForm)"
                :on-progress="uploadObj.onProgress('linkFileId')"
                :on-error="uploadObj.onError('linkFileId')"
                :on-remove="uploadObj.onRemove('linkFileId')"
              >
                <transition name="upload" mode="out-in">
                  <div class="upload-empty" v-if="!dataForm.linkFileId">
                    <i class="iconfont icon-icon_update upload-icon"></i>
                    <p class="upload-des">拖转文件至此或点击上传</p>
                  </div>
                  <div class="upload-content-files" v-else>
                    <div class="upload-content-item" v-for="(item, index) in uploadObj.linkFileId.fileList">
                      <el-tooltip content="删除" placement="top">
                        <i class="iconfont upload-content-item-close icon-a-ziyuan669" @click.self.stop="delUploadItem(item, index)"></i>
                      </el-tooltip>
                      <i class="iconfont icon-daimawenjian-mian upload-icon"></i>
                      <el-tooltip :content="item.fileName" placement="top" :disabled="!item.fileName">
                        <p class="upload-des">{{ item.fileName }}</p>
                      </el-tooltip>
                    </div>
                  </div>
                </transition>
              </el-upload>
            </el-form-item>
          </div>  
        </div>
        <!-- 动态链接 -->
        <div class="common-row row-between">
          <div class="common-item item-10" :style="{paddingBottom: getFileListPadding(uploadObj.dynamicLinkFileId)}">
            <label class="condition-label">动态链接库上传</label>
            <el-form-item class="condition-input" prop="dynamicLinkFileId">
              <el-upload
                class="upload"
                :ref="uploadObj.uploadRef('dynamicLinkFileId')"
                drag
                :action="uploadObj.uploadUrl"
                multiple
                :headers="uploadObj.headers"
                :show-file-list="uploadObj.dynamicLinkFileId.showFileList"
                :before-upload="uploadObj.beforeUpload('dynamicLinkFileId')"
                :on-success="uploadObj.onSuccess('dynamicLinkFileId', dataForm)"
                :on-progress="uploadObj.onProgress('dynamicLinkFileId')"
                :on-error="uploadObj.onError('dynamicLinkFileId')"
                :on-remove="uploadObj.onRemove('dynamicLinkFileId')"
              >
                <transition name="upload" mode="out-in">
                  <div class="upload-empty" v-if="!dataForm.dynamicLinkFileId">
                    <i class="iconfont icon-icon_update upload-icon"></i>
                    <p class="upload-des">拖转文件至此或点击上传</p>
                  </div>
                  <div class="upload-content-files" v-else>
                    <div class="upload-content-item" v-for="(item, index) in uploadObj.dynamicLinkFileId.fileList">
                      <el-tooltip content="删除" placement="top">
                        <i class="iconfont upload-content-item-close icon-a-ziyuan669" @click.self.stop="delAsyncUploadItem(item, index)"></i>
                      </el-tooltip>
                      <i class="iconfont icon-daimawenjian-mian upload-icon"></i>
                      <el-tooltip :content="item.fileName" placement="top" :disabled="!item.fileName">
                        <p class="upload-des">{{ item.fileName }}</p>
                      </el-tooltip>
                    </div>
                  </div>
                </transition>
              </el-upload>
            </el-form-item>
          </div>  
        </div>
        <div class="common-row">
          <!-- 源码上传 -->
          <div class="common-item item-10" :class="{'item-upload': uploadObj.sourceFileId.showFileList}">
            <label class="condition-label">源码上传</label>
            <el-form-item class="condition-input" prop="sourceFileId">
              <el-upload
                class="upload"
                :ref="uploadObj.uploadRef('sourceFileId')"
                drag
                :action="uploadObj.uploadUrl"
                :limit="1"
                :headers="uploadObj.headers"
                :show-file-list="uploadObj.sourceFileId.showFileList"
                :before-upload="uploadObj.beforeUpload('sourceFileId')"
                :on-success="uploadObj.onSuccess('sourceFileId', dataForm)"
                :on-progress="uploadObj.onProgress('sourceFileId')"
                :on-error="uploadObj.onError('sourceFileId')"
                :on-remove="uploadObj.onRemove('sourceFileId')"
                v-model:file-list="uploadObj.sourceFileId.fileList"
              >
                <transition name="upload" mode="out-in">
                  <div class="upload-empty" v-if="!dataForm.sourceFileId">
                    <i class="iconfont icon-icon_update upload-icon"></i>
                    <p class="upload-des">拖拽文件至此或点击上传</p>
                  </div>
                  <div class="upload-content" v-else>
                    <i class="iconfont icon-daimawenjian-mian upload-icon"></i>
                    <el-tooltip :content="uploadObj.sourceFileId.fileName" placement="top" :disabled="!uploadObj.sourceFileId.fileName">
                      <p class="upload-des">{{ uploadObj.sourceFileId.fileName }}</p>
                    </el-tooltip>
                  </div>
                </transition>
              </el-upload>
            </el-form-item>
          </div>
        </div>
      </div>
    </div>
   </el-form>
    <!-- 参数配置 -->
    <div class="data-show">
      <!-- 标题 -->
      <div class="data-actions data-title-between">
        <h3>参数配置</h3>
        <span class="aniTxtBtn action" @click="addParamter">添加参数</span>
      </div>
      <!-- 内容区 -->
      <div class="data-table params-container">
        <transition name="upload" mode="out-in">
          <div class="params-empty" v-if="dataForm.parameters.length < 1">
            <i class="iconfont icon-wushuju1 data-empty-icon"></i>
            <h3 class="data-empty">未设置参数请添加</h3>
          </div>
          <div v-else>
            <transition-group name="list">
              <div class="params-item" v-for="(item, index) in dataForm.parameters" :key="index">
                <!-- <el-form :ref="bindParameterRef(item, index)" :model="dataForm.parameters[index]" :rules="dataForm.parameters[index].rules"> -->
                <el-form :ref="bindParameterRef(item, index)" :model="item" :rules="item.rules">
                <span class="params-item-title">参数{{ index + 1 }}</span>
                <span class="params-item-del" @click="handleDelParameter(item, index)">删除</span>
                <div class="common-row row-between">
                  <div class="parameter-form-item item-5">
                    <label class="condition-label">参数名</label>
                    <el-form-item class="condition-input" prop="parameterCode">
                      <el-input type="text" placeholder="请输入英文参数名" v-model="item.parameterCode" />
                    </el-form-item> 
                  </div>
                  <!-- <div class="parameter-form-item item-5">
                    <label class="condition-label">是否关联选项</label>
                    <el-form-item class="condition-input radio-input" prop="isRelateOpt">
                      <el-radio @change="isRelateChange(item, index)" v-for="(it, ind) in parameterRelates" :key="ind" :label="it.label" :value="it.value" v-model="item.isRelateOpt">
                    </el-radio>
                    </el-form-item>
                  </div> -->
                  <div class="parameter-form-item item-5">
                    <label class="condition-label">选择参数类型</label>
                    <el-form-item class="condition-input radio-input" prop="parameterType">
                      <el-select @change="selectParameterType($event, item, index)" v-model="item.parameterType" clearable placeholder="请选择参数类型">
                        <el-option v-for="(it, ind) in parameterTypes" :key="ind" :label="it.label" :value="it.value" />
                      </el-select>
                    </el-form-item>
                  </div>
                </div>
                <!-- <div class="common-row row-between">
                  <div class="parameter-form-item item-5">
                    <label class="condition-label">选择参数类型</label>
                    <el-form-item class="condition-input radio-input" prop="parameterType">
                      <el-select @change="selectParameterType($event, item, index)" v-model="item.parameterType" clearable placeholder="请选择参数类型">
                        <el-option v-for="(it, ind) in parameterTypes" :key="ind" :label="it.label" :value="it.value" />
                      </el-select>
                    </el-form-item>
                  </div>
                  <div class="parameter-form-item item-5" v-if="item.isRelateOpt === 1">
                    <label class="condition-label">选择关联选项</label>
                    <el-form-item class="condition-input radio-input" prop="optId">
                      <el-cascader clearable v-model="item.optSelect" :options="stepOptions" @change="optIdChange($event, item)" />
                    </el-form-item>
                  </div>
                </div> -->
                <transition name="upload" mode="out-in">
                  <div v-if="item.parameterType == 0">
                    <div class="common-row row-between" >
                      <div class="parameter-form-item item-10">
                        <label class="condition-label">设置关联项及默认值</label>
                        <el-form-item class="condition-input radio-input" prop="enumValue">
                          <el-input 
                            clearable
                            type="text" 
                            placeholder="请输入选项值并回车确认" 
                            v-model="item.enumInput" 
                            @keyup.enter.native="handleCreateEnum(item.enumInput, item)"
                            @change="handleCreateEnum(item.enumInput, item)"
                          />
                        </el-form-item>
                      </div>
                    </div>
                    <div class="common-row row-between">
                      <div class="parameter-form-item item-10">
                        <label class="condition-label">选择设置默认值</label>
                        <el-form-item class="condition-input" prop="defValue">
                          <transition name="upload" mode="out-in">
                            <div class="enums-container" v-if="item.enums.length > 0">
                              <transition-group name="list">
                                <el-radio class="enum-item" v-model="item.defValue" v-for="(enumItem, enumInd) in item.enums" :label="enumItem" :value="enumItem" :key="enumInd">
                                  <span class="emum-item-content">{{ enumItem }}</span>
                                  <i class="iconfont icon-guanbi2 emum-item-close" @click.stop.prevent="handleCloseEnumItem(enumInd, item)"></i>
                              </el-radio>
                              </transition-group>
                            </div>
                            <div class="enums-empty" v-else>
                              <i class="iconfont icon-wushuju1 data-empty-icon"></i>
                              <h3 class="data-empty">未添加选项请输入添加</h3>
                            </div>
                          </transition>
                          
                        </el-form-item>
                      </div>
                    </div>
                  </div>
                  <div v-else-if="item.parameterType == 1">
                    <div class="common-row row-between">
                      <div class="parameter-form-item item-5">
                        <label class="condition-label">参数最小值</label>
                        <el-form-item class="condition-input radio-input" prop="minValue">
                          <el-input-number type="number" placeholder="请输入参数最小值" v-model.number="item.minValue" />
                        </el-form-item>
                      </div>
                      <div class="parameter-form-item item-5">
                        <label class="condition-label">参数最大值</label>
                        <el-form-item class="condition-input radio-input" prop="maxValue">
                          <el-input-number :min="item.minValue ? item.minValue : 0" type="number" placeholder="请输入参数最大值" v-model.number="item.maxValue" />
                        </el-form-item>
                      </div>
                    </div>
                    <div class="common-row row-between">
                      <div class="parameter-form-item item-5">
                        <label class="condition-label">参数默认值</label>
                        <el-form-item class="condition-input radio-input" prop="defValue">
                          <el-input-number type="number" :min="item.minValue ? item.minValue : 0" :max="item.maxValue ? item.maxValue : 0" placeholder="请输入参数默认数值" v-model.number="item.defValue" />
                        </el-form-item>
                      </div>
                    </div>
                  </div>
                  <div v-else-if="item.parameterType == 2">
                    <div class="common-row row-between">
                      <div class="parameter-form-item item-10">
                        <label class="condition-label">固定值</label>
                        <el-form-item class="condition-input radio-input" prop="defValue">
                          <el-input 
                            clearable
                            type="text" 
                            placeholder="请输入固定值" 
                            v-model="item.defValue" 
                          />
                        </el-form-item>
                      </div>
                    </div>
                  </div>
                </transition>
                <div class="common-row row-between">
                  <div class="parameter-form-item item-10">
                    <label class="condition-label">参数描述</label>
                    <el-form-item class="condition-input radio-input" prop="description">
                      <el-input v-model="item.description" maxlength="100" type="textarea" show-word-limit rows="4" resize="none" placeholder="请输入参数描述" />
                    </el-form-item>
                  </div>
                </div>
                </el-form>
              </div>
            </transition-group>
          </div>
        </transition>
      </div>
    </div>
    <!-- 底部的按钮 -->
    <div class="btn-groups">
      <button type="button" class="btn btn-normal" @click="back">取消</button>
      <button type="button" class="btn" @click="handleCreate">确定</button>
    </div>

  </div>
</template>
<script setup>
import useUserStore from '@/stores/user';
import useAppStore from '@/stores/app';
import { getToken } from '@/utils/storage';
import { ref, computed, watch, onMounted } from 'vue';
import { api, global } from '@/utils/status';
import { deepCopy } from '@/utils/utils.js';
import { ElMessage } from 'element-plus';
import { 
  // 创建模块
  createModuleAlgo, 
  // 查看模块详情
  getModuleAlgoDetail, 
  // 编辑模块
  setModuleAlgo 
} from '@/api/module';
import { getModuleLibs } from '@/api/moduleLib.js';
import { useRouter, useRoute } from 'vue-router';
import * as rule from '@/utils/rules.js';
import * as fileApi from '@/api/file';

const defaultParameter = {
  // 是否关联选项
  isRelateOpt: 0,
  // 关联选项id
  optId: null,
  // 参数类型
  parameterType: null,
  // 参数名
  parameterCode: '',
  // 默认值
  defValue: null,
  // 下拉选项的可选值
  enumValue: null,
  maxValue: null,
  minValue: null,
  description: '',
  // 关联选项选择绑定数组
  optSelect: [],
  enumInput: '',
  enums: [],
  formRef: null,
  rules: {
    parameterCode: [{ 
      required: true, 
      // validator: rule.verifyObj.chineseReg, 
      validator(rule, value, callback){
        let parameterCodes = dataForm.value.parameters.map(item => item.parameterCode);
        let sameParameterCodes = parameterCodes.filter(name => name === value);
        if (value == undefined || value == null || value == ''){
          return callback(new Error('输入不能为空'));
        } else if (/[\u4e00-\u9fa5]/.test(value)){
          return callback(new Error('输入不能包含中文字符'));
        } else if (sameParameterCodes.length > 1) {
          return callback(new Error('不能创建相同参数名的参数'));
        } else {
          callback()
        }
      },
      trigger: ['blur', 'change'] }],
    isRelateOpt: rule.createRequiredRule('请选择参数关联性'),
    parameterType: rule.createRequiredRule('请选择参数类型'),
    defValue: rule.createRequiredRule('请指定参数默认值')
  }
};
// 参数是否关联选项数组
const parameterRelates = api.module.parameter.relates;
// 参数类型数组
const parameterTypes = api.module.parameter.type;
// ============> datas
// 算法平台
const systems = ref(api.common.systems);
const defaults = ref(api.common.defaults);
const appStore = useAppStore();
const userStore = useUserStore();
const router = useRouter();
const route = useRoute();
const isSet = ref(false);
// 表单验证规则
const rules = ref({
  // name: rule.moduleAlgo,
  name: [ { validator: rule.verifyObj.chineseReg, trigger: ['blur', 'change'] } ],
  description: rule.algoDes,
  moduleLibId: rule.createRequiredRule('模块不能为空'),
  system: rule.createRequiredRule('算法平台不能为空'),
  linkFileId: rule.createRequiredRule('请上传静态链接库'),
  isDefault: rule.createRequiredRule('请选择模块是否默认'),
  parameters: []
});
const createForm = ref(null);
// 表单对象
const dataForm = ref({
  // userId: userStore.userId,
  name: '',
  // 模块库
  moduleLibId: null,
  moduleLibSelect: [],
  owner: '',
  description: '',
  // 算法平台
  system: 'WINDOWS',
  isDefault: null,
  // 静态链接(必填项)
  linkFileId: '',
  // 动态链接
  dynamicLinkFileId: '',
  // 源码上传(可选)
  sourceFileId: '',
  // 参数json数组
  algoModuleParams: [],
  type: api.sysType.IMAGE,
  createFlag: false,
  parameters: []
});
// 拉取或者初始的静态链接库、动态链接库、源码文件id保存栈
let saveFileIds = [];
// 原文件id包含的要删除文件
let includeDelFiles = [];
// 原文件id不包含的要删除文件
let excludeDelFiles = [];
// 模块库列表
const moduleLibrarys = ref([]);
// 参数关联选项绑定选择数组
const stepOptions = ref([]);
const imgStepOptions = [
  {
    value: 1,
    label: '选择支持载体格式类型',
    children: [
      { value: '110001', label: 'JPEG' },
      { value: '110002', label: 'BMP' },
      { value: '110003', label: 'TIFF' },
      { value: '110004', label: 'PNG' }
    ]
  },
  {
    value: 2,
    label: '是否支持社交网络信道鲁棒隐写',
    children: [
      { value: '210001', label: '是' },
      { value: '210002', label: '否' }
    ]
  },
  {
    value: 3,
    label: '选择信道',
    children: [
      { value: '220001', label: 'Twitter' },
      { value: '220002', label: '微博' },
      { value: '220003', label: 'Facebook' },
      { value: '220004', label: '微信' }
    ]
  },
  {
    value: 4,
    label: '选择隐写编码算法',
    children: [
      { value: '310001', label: '矩阵码' },
      { value: '310002', label: '湿纸码' },
      { value: '310003', label: 'STC' },
      { value: '310004', label: '极化隐写码' },
      { value: '310005', label: '双层STC码' }
    ]
  },
  {
    value: 5,
    label: '选择隐写失真代价函数',
    children: [
      { value: '410001', label: 'JPEG-UNIWARD' },
      { value: '410002', label: 'FAST-JPEG-UNIWARD' },
      { value: '410003', label: 'JPEG-SI-UNIWARD' },
      { value: '410004', label: 'JPEG-UED' },
      { value: '410005', label: 'JPEG-UERD' },
      { value: '410006', label: 'JPEG-NAS' },
      { value: '410007', label: 'ROBUST-TCB' },
      { value: '410008', label: 'ROBUST-CRE' },
      { value: '410009', label: 'SPATIAL-UNIWARD' },
      { value: '410010', label: 'SPATIAL-HILL' },
      { value: '410011', label: 'SPATIAL-HUGO' },
      { value: '410012', label: 'SPATIAL-WOW' }
    ]
  },
];
const videoStepOptions = [
  {
    value: 1,
    label: '选择支持载体格式类型',
    children: [
      { value: '110001', label: 'MP4' },
      { value: '110002', label: 'MKV' },
      { value: '110003', label: 'AVI' }
    ]
  },
  {
    value: 2,
    label: '是否支持社交网络信道鲁棒隐写',
    children: [
      { value: '210001', label: '是' },
      { value: '210002', label: '否' }
    ]
  },
  {
    value: 3,
    label: '选择信道',
    children: [
      { value: '220001', label: 'YouTube' },
      { value: '220002', label: '抖音' }
    ]
  },
  {
    value: 4,
    label: '选择鲁棒视频隐写算法',
    children: [
      { value: '230001', label: '先验优选策略' },
      { value: '230002', label: 'PCA优选策略' }
    ]
  },
  {
    value: 5,
    label: '选择编码器类型',
    children: [
      { value: '310001', label: 'x264' },
      { value: '310002', label: 'x265' }
    ]
  },
  {
    value: 6,
    label: '选择嵌入域',
    children: [
      { value: '410001', label: '运动向量域' },
      { value: '410002', label: '帧内预测模式域' },
      { value: '410003', label: '帧间预测模式域' },
      { value: '410004', label: '变换系数域' },
      { value: '410005', label: '伴音域' }
    ]
  },
  {
    value: 7,
    label: '选择调制模式',
    children: [
      { value: '510001', label: '哈夫曼码字' },
      { value: '510002', label: '编码系数' },
      { value: '510003', label: '快速' },
      { value: '510004', label: '安全' }
    ]
  },
];
const audioStepOptions = [
  {
    value: 1,
    label: '选择隐写嵌入域',
    children: [
      { value: '110001', label: '低比特位域' },
      { value: '110002', label: '哈夫曼码字域' },
      { value: '110003', label: '编码系数域' },
      { value: '110004', label: '编码系数符号位域' },
      { value: '110005', label: '编码系数溢出位域' }
    ]
  },
  {
    value: 2,
    label: '音频隐写代价配置',
    children: [
      { value: '210001', label: '启用' },
      { value: '210002', label: '不启用' }
    ]
  },
  {
    value: 3,
    label: '代价类型选择',
    children: [
      { value: '220001', label: 'JED代价' },
      { value: '220002', label: '声学代价' }
    ]
  },
  {
    value: 4,
    label: '隐写码类型选择',
    children: [
      { value: '230001', label: 'STC' },
      { value: '230002', label: 'SPC' }
    ]
  },
];



// 上传路径
const uploadObj = ref({
  url: `${import.meta.env.VITE_FILE_BASE_API}${fileApi.uploadUrl}`,
  uploadUrl: `${import.meta.env.VITE_FILE_BASE_API}${fileApi.uploadUrl}`,
  headers: {},
  uploadRef(key){
    return function (dom){
      if (dom){
        uploadObj.value[key].dom = dom;
      }
    }
  },
  beforeUpload(key, limit = api.upload.commonSizeLimit){
    return function (file){
      if (uploadObj.value[key].uploading){
        ElMessage.warning('当前有文件正在上传，请稍后重试');
        return false;
      }
      let extension = (file.size < limit) && (file.size > 0);
      if (!extension) {
        ElMessage.warning(`上传文件不符合大小限制，文件须小于${limit / (1024 * 1024)}M 且大于 0`);
        return extension;
      }
      // todo - 这里做文件扩展名的校验
      let fileType = file.name.substring(file.name.lastIndexOf('.') + 1).toLowerCase();
      if (key === 'linkFileId' && dataForm.value.system === 'WINDOWS'){
        extension = fileType == 'lib' || fileType == 'h' || fileType == 'a' ? true : false;
        if (!extension){
          ElMessage.warning('上传文件须为 lib / a / h 文件!');
        }
      }
      if (key === 'linkFileId' && dataForm.value.system === 'ANDROID'){
        extension = fileType == 'a' || fileType === 'la' || fileType == 'h' || fileType == 'so' ? true : false;
        if (!extension){
          ElMessage.warning('上传文件须为a/la/h文件!');
        }
      }
      if (key === 'dynamicLinkFileId' && dataForm.value.system === 'WINDOWS'){
        extension = fileType == 'dll' ? true : false;
        if (!extension){
          ElMessage.warning('上传文件须为 dll 文件');
        }
      }
      if (key === 'dynamicLinkFileId' && dataForm.value.system === 'ANDROID'){
        extension = fileType == 'so' ? true : false;
        if (!extension){
          ElMessage.warning('上传文件须为 so 文件');
        }
      }
      uploadObj.value[key].fileName = extension ? file.name : '';
      uploadObj.value[key].showFileList = true;
      if ((key === 'linkFileId' || key === 'dynamicLinkFileId') && extension){
        uploadObj.value[key].fileLength++;
      }
      return extension;
    }
  },
  onSuccess(key, data){
    return function (e){
      uploadObj.value[key].showFileList = false;
      uploadObj.value[key].uploading = false;
      if (e.code === api.code.SUCCESS && (key == 'linkFileId' || key == 'dynamicLinkFileId')){
        // ElMessage.success('上传成功');
        uploadObj.value[key].fileList.push(e.data);
        uploadObj.value[key].fileLength--;
        data[key] = uploadObj.value[key].fileList.reduce((ids, item, index) => {
          if (index < (uploadObj.value[key].fileList.length - 1)) {
            ids += `${item.id},`;
          } else {
            ids += item.id;
          }
          return ids;
        }, '')
      } else if (e.code === api.code.SUCCESS && key != 'linkFileId' && key != 'dynamicLinkFileId') {
        uploadObj.value[key].dom.clearFiles();
        ElMessage.success('上传成功');
        uploadObj.value[key].fileName = e.data.fileName;
        if (data[key]){
          fileApi.delFile({fileId: data[key]})
        }
        data[key] = e.data.id;
      } else {
        let msg = e.msg || e.message || '上传失败，请稍后重试或联系管理员';
        ElMessage({
          type: 'error',
          duration: 1500,
          message: msg
        });
      }
    }
  },
  onProgress(key){
    return function (e){
      uploadObj.value[key].showFileList = true;
      uploadObj.value[key].uploading = true;
    }
  },
  onError(key){
    return function (e){
      let message = e.msg || e.message || '上传失败，请稍后重试或联系管理员';
      ElMessage({
        type: 'error',
        duration: 1500,
        message
      });
      uploadObj.value[key].showFileList = false;
      uploadObj.value[key].uploading = false;
      if (key !== 'linkFileId' && key !== 'dynamicLinkFileId') {
        uploadObj.value[key].dom.clearFiles();
        uploadObj.value[key].fileName = '';
      } else {
        uploadObj.value[key].fileLength--;
      } 
    }
  },
  onRemove(key){
    return function (e){
      uploadObj.value[key].showFileList = false;
      uploadObj.value[key].uploading = false;
      uploadObj.value[key].dom.clearFiles();
      uploadObj.value[key].fileName = '';
    }
  },
  linkFileId: {
    fileList: [],
    fileLength: 0,
    dom: null,
    showFileList: false,
    fileName: '',
    uploading: false
  },
  dynamicLinkFileId: {
    fileList: [],
    fileLength: 0,
    dom: null,
    showFileList: false,
    fileName: '',
    uploading: false
  },
  sourceFileId: {
    dom: null,
    showFileList: false,
    fileName: '',
    uploading: false
  }
});
uploadObj.value.headers['Authorization'] = userStore.token ? userStore.token : getToken();
const getFileListPadding = computed(() => {
  return function (upload){
    let paddingBottom = '20px';
    if (upload.showFileList){
      paddingBottom = `${upload.fileLength * 35 + 20}px`;
    }
    return paddingBottom;
  }
});


// ============> hooks
isSet.value = route.query && route.query.id ? true : false;
// getModules();
init();
// ============> methods
function getModules(){
  return getModuleLibs()
    .then(res => {
      if (res && Array.isArray(res) && res.length > 0) {
        moduleLibrarys.value = res
      }
    })
}
async function init(){
  // 初始化参数配置的关联选项绑定数组
  switch (userStore.currentModal){
    case global.modal.IMAGE:
      stepOptions.value = imgStepOptions;
      break;
    case global.modal.VIDEO:
      stepOptions.value = videoStepOptions;
      break;
    case global.modal.AUDIO:
      stepOptions.value = audioStepOptions;
      break;
  }
  await getModules();
  if (!isSet.value) {
    return;
  }
  getModuleAlgoDetail({ id: route.query.id })
    .then(res => {
      if (res){
        dataForm.value = {...dataForm.value, ...res};
        dataForm.value.moduleLibSelect = getShowModuleLib();
        // console.log(res)
        uploadObj.value.linkFileId.fileList = dataForm.value.linkFiles ? dataForm.value.linkFiles : [];
        uploadObj.value.dynamicLinkFileId.fileList = dataForm.value.dynamicLinkFiles ? dataForm.value.dynamicLinkFiles : [];
        uploadObj.value.sourceFileId.fileName = dataForm.value.sourceFileId ? dataForm.value.sourceFileName : '';
        dataForm.value.linkFileId && (saveFileIds.push(...dataForm.value.linkFileId.split(',')));
        dataForm.value.dynamicLinkFileId && (saveFileIds.push(...dataForm.value.dynamicLinkFileId.split(',')));
        dataForm.value.sourceFileId && (saveFileIds.push(...dataForm.value.sourceFileId.split(',')));
        // console.log(saveFileIds)
        if (dataForm.value.algoModuleParams && Array.isArray(dataForm.value.algoModuleParams) && dataForm.value.algoModuleParams.length > 0){
          dataForm.value.algoModuleParams.forEach(item => {
            let parameter = deepCopy(defaultParameter);
            parameter = {...parameter, ...item};
            if (parameter.isRelateOpt === 1) {
              parameter.rules.optId = rule.createRequiredRule('请选择要关联的选项');
            }
            if (parameter.optId){
              let stepObj = stepOptions.value.find(step => {
                let res = step.children.find(child => child.value === parameter.optId);
                return !!res;
              });
              !!stepObj && (parameter.optSelect = [stepObj.value, parameter.optId]);
            }
            if (item.parameterType === 0){
              parameter.enums = item.enumValue.split(',');
              parameter.rules.enumValue = rule.createRequiredRule('参数选项未设置');
            } else if (item.parameterType === 1) {
              parameter.defValue = + item.defValue;
              parameter.minValue = + item.minValue;
              parameter.maxValue = + item.maxValue;
              parameter.rules.minValue = rule.createRequiredRule('请设置参数最小值');
              parameter.rules.maxValue = rule.createRequiredRule('请设置参数最大值');
            }
            dataForm.value.parameters.push(parameter)
          });
        }
      } else {
        ElMessage.error('获取算法详情失败');
      }
    })
    .catch(err => {
      console.log(err)
      // ElMessage.error('获取算法详情失败');
    })
}
// 编辑模式下回显模块库路径
function getShowModuleLib(){
  let resultArr = [];
  if (moduleLibrarys.value.length > 1){
    let moduleLibs = flatArr(moduleLibrarys.value);
    getIdFromArr(dataForm.value.moduleLibId, moduleLibs, resultArr);
  } 
  function getIdFromArr(id, arr, result){
    let resultItem = arr.find(item => item.id === id);
    result.unshift(id);
    if (resultItem.parentId !== '0') {
      getIdFromArr(resultItem.parentId, arr, result);
    }
  }
  return resultArr;
}
function flatArr(arr){
  let result = [];
  arr.forEach(item => {
    result.push(item);
    if (item.children && Array.isArray(item.children)){
      result.push(flatArr(item.children))
    }
  });
  return result.flat(Infinity);
}
function selectModuleLibs(e){
  if (e && Array.isArray(e) && e.length > 0){
    dataForm.value.moduleLibId = e.at(-1);
  } else {
    dataForm.value.moduleLibId = null;
  }
}
function delUploadItem(item, index){
  let itemId = item.id;
  let selectIds = dataForm.value.linkFileId.split(',');
  if (itemId){
    /*
    fileApi.delFile({fileId: itemId})
      .then(res => {
        ElMessage.success('删除成功！');
        selectIds.splice(selectIds.findIndex(id => id == itemId), 1);
        uploadObj.value.linkFileId.fileList.splice(index, 1);
        dataForm.value.linkFileId = selectIds.join(',');
      })
      .catch(err => {
        console.log(err)
      })
    */
    selectIds.splice(selectIds.findIndex(id => id == itemId), 1);
    uploadObj.value.linkFileId.fileList.splice(index, 1);
    dataForm.value.linkFileId = selectIds.join(',');
    ElMessage.success('删除成功！');
    if (saveFileIds.includes(itemId)) {
      includeDelFiles.push(itemId);
    } else {
      excludeDelFiles.push(itemId);
    }
  } else {
    ElMessage.error('未提供删除信息，请联系稍后重试或联系管理员');
  }
}
function delAsyncUploadItem(item, index){
  let itemId = item.id;
  let selectIds = dataForm.value.dynamicLinkFileId.split(',');
  if (itemId){
    /*
    fileApi.delFile({fileId: itemId})
      .then(res => {
        ElMessage.success('删除成功！');
        selectIds.splice(selectIds.findIndex(id => id == itemId), 1);
        uploadObj.value.dynamicLinkFileId.fileList.splice(index, 1);
        dataForm.value.dynamicLinkFileId = selectIds.join(',');
      })
      .catch(err => {
        console.log(err)
      })
        */
      selectIds.splice(selectIds.findIndex(id => id == itemId), 1);
      uploadObj.value.dynamicLinkFileId.fileList.splice(index, 1);
      dataForm.value.dynamicLinkFileId = selectIds.join(',');
      ElMessage.success('删除成功！');
      if (saveFileIds.includes(itemId)) {
        includeDelFiles.push(itemId);
      } else {
        excludeDelFiles.push(itemId);
      }
  } else {
    ElMessage.error('未提供删除信息，请联系稍后重试或联系管理员');
  }
}
// 点击添加参数
function addParamter(){
  dataForm.value.parameters.push(deepCopy(defaultParameter));
}
function bindParameterRef(item, index){
  return function (dom){
    if (dom){
      item.formRef = dom;
    }
  }
}
// 是否关联选项选择事件
function isRelateChange(item, index){
  if (item.isRelateOpt === 1){
    item.rules.optId = rule.createRequiredRule('请选择要关联的选项');
  } else {
    item.rules.optId = null;
  }
}
// 选择关联选项
function optIdChange(e, item){
  if (e && Array.isArray(e) && e.length > 1){
    item.optId = e[1];
  } else if (!e){
    item.optId = null;
  }
}
// 选择参数类型
function selectParameterType(e, item, index){
  if (e !== undefined && e !== null && e !== ''){
    switch (e){
      case 0:
        item.rules.enumValue = rule.createRequiredRule('参数选项未设置');
        item.maxValue = null;
        item.minValue = null;
        item.defValue = null;
        break;
      case 1: 
        item.rules.minValue = rule.createRequiredRule('请设置参数最小值');
        item.rules.maxValue = rule.createRequiredRule('请设置参数最大值');
        item.enumValue = null;
        item.defValue = null;
        item.enums = [];
        item.enumInput = '';
        break;
      case 2:
        item.rules.enumValue = null;
        item.rules.minValue = null;
        item.rules.maxValue = null;
        item.enumValue = null;
        item.defValue = null;
        item.enums = [];
        item.enumInput = '';
        item.maxValue = null;
        item.minValue = null;
        break;
    }
  } else {
    item.rules.enumValue = null;
    item.rules.minValue = null;
    item.rules.maxValue = null;
    item.enumValue = null;
    item.defValue = null;
    item.enums = [];
    item.enumInput = '';
    item.maxValue = null;
    item.minValue = null;
  }
}
// 输出创建枚举选项事件
function handleCreateEnum(value, item){
  if (item.enums.includes(value)){
    ElMessage.warning('该输入项已创建，请重新输入');
    return;
  }
  // if (value !== undefined && value !== '' && value !== null){
  //   item.enums.push(value);
  //   item.enumInput = '';
  //   item.enumValue = item.enums.join(',');
  // } else {
  //   ElMessage.warning('选项值不能为空， 请输入选项值')
  // }
  if (value !== undefined && value !== '' && value !== null){
    item.enums.push(value);
    item.enumInput = '';
    item.enumValue = item.enums.join(',');
  }
}
function handleCloseEnumItem(index, item){
  let closeEnum = item.enums.find((it, ind) => ind === index);
  if (closeEnum === item.defValue){
    item.defValue = null;
  }
  item.enums.splice(index, 1);
  item.enumValue = item.enums.join(',')
}
// 删除参数
function handleDelParameter(item, index){
  dataForm.value.parameters.splice(index, 1);
}
// 提交请求前转换parameters
function changeParameters(){

}
function handleCreate(){
  if (dataForm.value.createFlag){
    ElMessage.warning('当前正在执行，请稍后');
    return;
  }
  let apiFn = isSet.value ? setModuleAlgo : createModuleAlgo;
  let loadingTxt = isSet.value ? '算法修改中...' : '算法创建中...';
  let successTxt = isSet.value ? '修改算法成功！' : '创建算法成功！';
  if (dataForm.value.parameters.length > 0) {
    let validPromises = [];
    dataForm.value.parameters.forEach((item) => {
      validPromises.push(new Promise((resolve, reject) => {
        item.formRef.validate(valid => {
          if (valid) {
            resolve();
          } else {
            reject();
          }
        })
      }));
    });
    Promise.all(validPromises)
      .then(() => {
        createForm.value.validate(valid => {
          if (valid){
            dataForm.value.createFlag = true;
            dataForm.value.algoModuleParams = dataForm.value.parameters;
            appStore.openLoading(loadingTxt);
            apiFn(dataForm.value)
              .then(res => {
                ElMessage.success(successTxt);
                // 删除文件
                afterConfirm();
                router.replace({ name: 'moduleManage'});
              })
              .catch(err => {
                dataForm.value.createFlag = false;
              })
              .finally(() => {
                dataForm.value.algoModuleParams = [];
                dataForm.value.createFlag = false;
                appStore.closeLoading();
              })
          } else {
            console.log('验证失败')
            ElMessage.warning('提交信息验证失败，请核对后提交');
          }
        })
      })
      .catch(() => {
        console.log('验证失败')
        ElMessage.warning('提交信息验证失败，请核对后提交');
      })
  } else {
    createForm.value.validate(valid => {
      if (valid){
        dataForm.value.createFlag = true;
        dataForm.value.algoModuleParams = dataForm.value.parameters;
        appStore.openLoading(loadingTxt);
        apiFn(dataForm.value)
          .then(res => {
            ElMessage.success(successTxt);
            // 删除文件
            afterConfirm();
            router.replace({ name: 'moduleManage'});
          })
          .catch(err => {
            dataForm.value.createFlag = false;
          })
          .finally(() => {
            dataForm.value.createFlag = false;
            appStore.closeLoading();
          })
      } else {
        console.log('验证失败')
        ElMessage.warning('提交信息验证失败，请核对后提交');
      }
    })
  }
  
}
function back(){
  if (excludeDelFiles.length > 0) {
    excludeDelFiles.forEach(itemId => {
      fileApi.delFile({fileId: itemId});
    });
  }
  router.back();
}
// 创建/编辑成功后回调删除文件
function afterConfirm(){
  if (excludeDelFiles.length > 0) {
    excludeDelFiles.forEach(itemId => {
      fileApi.delFile({fileId: itemId});
    });
  }
  if (includeDelFiles.length > 0){
    includeDelFiles.forEach(itemId => {
      fileApi.delFile({fileId: itemId});
    });
  }
}


</script>
<style lang='scss' scoped>
@import '@/assets/styles/mixin.scss';
.row-between {
  justify-content: space-between;
}
.item-3 {
  width: 30%
}
.item-10 {
  width: 100%;
  height: auto;
  padding: 20px 0;
  .condition-label {
    width: 15%;
  }
  .condition-input {
    width: 80%;
  }
}
.item-10-spe {
  width: 100%;
  .condition-label {
    width: 15%;
  }
  .condition-input {
    width: 80%;
  }
  &::v-deep .el-form-item__content {
    align-items: center!important;
  }
}
.item-5 {
  width: 49%;
  height: auto;
  padding: 15px 0;
}
.upload {
  width: 100%;
  min-height: 120px;
  height: 120px;
  &::v-deep .el-upload {
    @include wh-100;
    // height: 100%!important;
    .el-upload-dragger {
      @include wh-100;
      border-color: var(--color-main);
      padding: 0;
      .upload-empty {
        @include wh-100;
        @include flex-all-center;
        flex-direction: column;
        .upload-icon {
          font-size: 30px;
          color: var(--color-gray-10);
        }
        .upload-des {
          color: var(--color-gray-10);
        }
      }
      .upload-content {
        @include wh-100;
        @include flex-all-center;
        flex-direction: column;
        .upload-icon {
          font-size: 30px;
          color: var(--color-main);
        }
        .upload-des {
          color: var(--color-main);
        }
      }
      .upload-content-files {
        @include wh-100;
        display: flex;
        flex-wrap: wrap;
        align-items: center;
        justify-content: center;
        overflow-y: auto;
        @include scrollBar;
        .upload-content-item {
          position: relative;
          width: 100px;
          height: 80px;
          margin: 15px 10px;
          border: 2px solid var(--color-main);
          border-radius: 8px;
          background-color: var(--color-main-9);
          @include flex-all-center;
          flex-direction: column;
          .upload-icon {
            font-size: 30px;
            color: var(--color-white-10);
          }
          .upload-des {
            display: inline-block;
            color: var(--color-white-10);
            width: 100%;
            text-align: center;
            @include text-overflow-ellipsis;
          }
          .upload-content-item-close {
            position: absolute;
            top: -8px;
            right: -8px;
            color: var(--color-white-10);
            font-size: 10px;
            width: 20px;
            height:20px;
            text-align: center;
            line-height: 20px;
            border-radius: 50%;
            background-color: red;
          }
        }
      }
    }
  }
  &::v-deep .el-upload-list > .el-upload-list__item.is-success {
    display: none;
  }
}
.btn-groups {
  margin-top: 20px;
  text-align: center;
  .btn {
    margin: 0 20px;
  }
}
.data-title-between {
  @include flex-between-center;
  .data-title-actions {
    display: flex;
  }
}
.params-container {
  padding: 20px;
  .params-empty {
    width: 100%;
    height: 180px;
    border: 2px solid var(--color-main);
    border-radius: 4px;
    background-color: var(--color-gray-5);
    @include inset-shadow-main-8;
    @include flex-all-center;
    flex-direction: column;
    .data-empty {
      color: var(--color-main);
      font-size: 20px;
    }
    // 无数据图标
    .data-empty-icon {
      color: var(--color-main);
      font-size: 80px;
    }
  }
  .params-item {
    width: 100%;
    position: relative;
    border: 2px solid var(--color-main);
    border-radius: 4px;
    background-color: var(--color-gray-2);
    @include inset-shadow-main-8;
    padding: 10px 0;
    margin-bottom: 28px;
    .params-item-title {
      position: absolute;
      width: 60px;
      height: 30px;
      background-color: var(--color-main);
      color: var(--color-white-10);
      text-align: center;
      line-height: 30px;
      font-weight: bold;
      top: -15px;
      left: 20px;
      border-radius: 10px;
    }
    .params-item-del {
      position: absolute;
      width: 60px;
      height: 30px;
      right: 20px;
      top:-15px;
      text-align: center;
      line-height: 26px;
      font-weight: bold;
      border: 2px solid var(--color-main);
      border-radius: 10px;
      background-color: var(--color-white-10);
      color: var(--color-main);
      cursor: pointer;
      transition: all 0.3s linear;
      &:hover {
        background-color: var(--color-red);
        color: var(--color-white-10);
        border: 2px solid var(--color-red);
      }
    }
  }
}
.enums-container {
  width: 100%;
  height: 120px;
  border: 2px solid var(--color-main);
  border-radius: 4px;
  background-color: var(--color-white-10);
  // @include inset-shadow-main-8;
  padding: 20px;
  display: flex;
  flex-wrap: wrap;
  overflow-y: auto;
  @include scrollBar;
}
.enums-empty {
  width: 100%;
  height: 120px;
  @include flex-all-center;
  flex-direction: column;
  border: 2px solid var(--color-main);
  border-radius: 4px;
  background-color: var(--color-white-10);
  // @include inset-shadow-main-8;
  .data-empty {
    color: var(--color-main);
    font-size: 20px;
  }
  // 无数据图标
  .data-empty-icon {
    color: var(--color-main);
    font-size: 40px;
  }
}
.enum-item.el-radio {
  width: 30%;
  margin: 0 10px 20px;
  &::v-deep .el-radio__label {
    width: 100%;
    padding: 0 30px 0 0;
    text-align: center;
    position: relative;
    transition: all 0.3s linear;
    .emum-item-content {
      width: 100%;
      display: inline-block;
      color: var(--color-main);
    }
    .emum-item-close {
      color: var(--color-main);
      width: 30px;
      height: 30px;
      position: absolute;
      right: 1px;
      top: 1px;
    }
  }
}
.enum-item.el-radio.is-checked::v-deep .el-radio__label {
  .emum-item-content {
    color: var(--color-white-10);
  }
  .emum-item-close {
    color: var(--color-white-10);
  }
}
</style>